import * as THREE from 'three'
import proj4 from 'proj4'

export class Tool {
  /**
   * 获取Object模型里面的mesh对象，并做相应的处理
   * @param {*} object3d 要查询的object对象
   * @param {*} detail 处理函数，参数是mesh对象
   */
  getMesh (object3d, detail) {
    if (object3d) {
      if (Object.prototype.hasOwnProperty.call(object3d, "children") && object3d.children.length > 0) {
        for (let i = 0; i < object3d.children.length; i++) {
          let child = object3d.children[i];
          if (child.type === 'Mesh') {
            detail(child)
          } else {
            this.getMesh(child, detail)
          }
        }
      } else {
        detail(object3d)
      }
    }
  }
  /** 闪烁材质 */
  flicker (object3d) {
    const minOpacity = 0.1
    const maxOpacity = 0.3
    const detail = (mesh) => {
      mesh.material.transparent = true
      let flag = 1
      let ani = () => {
        if (mesh.material.opacity < minOpacity) {
          flag = 1
        } else if (mesh.material.opacity > maxOpacity) {
          flag = -1
        }
        mesh.material.opacity += 0.007 * flag
        requestAnimationFrame(ani)
      }
      ani()
    }
    this.getMesh(object3d, detail)
  }
  /* threejs自带坐标转换，还不太会用 */
  lglt2xyz ({ lng, lat }, radius = 6371000) {
    const theta = (90 + lng) * (Math.PI / 180)
    const phi = (90 - lat) * (Math.PI / 180)
    return (new THREE.Vector3()).setFromSpherical(new THREE.Spherical(radius, phi, theta))
  }
  /* proj4将经纬度转为笛卡尔坐标，1刻度=1米，但是有误差，需要后期优化 */
  axisChange ({ lng, lat }) {
    let firstProjection = proj4('EPSG:4326')
    let secondProjection = proj4('EPSG:3857')
    return proj4(firstProjection, secondProjection, [lng, lat])
  }
  /* 将经纬度转为笛卡尔坐标系的xyz坐标 */
  lngLatToXyz ({ lng, lat, height = 0, scale = 1 }) {
    let x, y
    let xy = this.axisChange({ lng, lat })
    x = xy[0] - this.lng * this.scale * (scale)
    y = xy[1] - this.lat * this.scale * (scale)
    return new THREE.Vector3(x, height, y * -1)
  }
  /** 传入经纬度和空间坐标，输出空间坐标 */
  /** 后续完成！！！！！！！！！！！！！！！！！*/
  /** 后续完成！！！！！！！！！！！！！！！！！*/
  /** 后续完成！！！！！！！！！！！！！！！！！*/
  /** 后续完成！！！！！！！！！！！！！！！！！*/
  /** 后续完成！！！！！！！！！！！！！！！！！*/
  /** 后续完成！！！！！！！！！！！！！！！！！*/
  /** 后续完成！！！！！！！！！！！！！！！！！*/
  /** 后续完成！！！！！！！！！！！！！！！！！*/
  /** 后续完成！！！！！！！！！！！！！！！！！*/
  /** 后续完成！！！！！！！！！！！！！！！！！*/
  /** 后续完成！！！！！！！！！！！！！！！！！*/
  /** 后续完成！！！！！！！！！！！！！！！！！*/
  /** 后续完成！！！！！！！！！！！！！！！！！*/
  /** 后续完成！！！！！！！！！！！！！！！！！*/
  /**
   * 开启模型对象的阴影效果
   * @param object3d ThreeJS创建的模型对象
   */
  openShadow (object3d) {
    this.getMesh(object3d, (child) => {
      child.castShadow = true
      child.receiveShadow = true
    })
  }
  /**
   * 获取Object模型里面的mesh对象，并做相应的处理
   * @param {*} object3d 要查询的object对象
   * @param {*} detail 处理函数，参数是mesh对象
   */
  // getMesh (object3d, detail) {
  //   if (Object.prototype.hasOwnProperty.call(object3d, "children") && object3d.children.length > 0) {
  //     for (let i = 0; i < object3d.children.length; i++) {
  //       let child = object3d.children[i];
  //       if (child.type === 'Mesh') {
  //         detail(child)
  //       } else {
  //         this.getMesh(child, detail)
  //       }
  //     }
  //   }
  // }
  /**
   * 将普通的xyz对象转换成three需要的Vector3
   * @param {*} points item为xyz的数组
   * @returns item为Vector3的数组
   */
  toThreePoints (points) {
    let list = []
    for (let i = 0; i < points.length; i++) {
      const item = points[i];
      let point = new THREE.Vector3(item.x, item.y, item.z)
      list.push(point)
    }
    return list
  }
  /**
   * 将三维顶点坐标数组转换为Vector3
   * @param {*} attribute 三维顶点坐标数组
   * @returns item为Vector3的数组
   */
  att2Points (attribute) {
    let attributeList = []
    for (let i = 0; i < attribute.length; i += 3) {
      attributeList.push({
        x: attribute[i],
        y: attribute[i + 1],
        z: attribute[i + 2],
      })
    }
    return this.toThreePoints(attributeList)
  }
}
